unlink("banner.png")

file.copy("../images/banner1.png", "banner.png")

banner

Source code: https://github.com/markziemann/cryptoblog/blob/main/alerts/alerts.Rmd

Intro

In the backtesting analysis, I have established different profitable strategies for timing entry/exits. Click on the hyperlinks below to see how these signals were identified.

  1. Simple moving averages for BTC and ETH.

  2. Moving average crosses for BTC and ETH.

  3. Directional movement index (DMI) for BTC and ETH.

  4. True strength index (TSI) for BTC and ETH.

  5. Stochastic oscillator (stoch) for BTC and ETH.

  6. Double RSI and BTC and ETH.

This script will examine the price action and these trade signals just before the daily close. If the signal is TRUE, it is bullish and if FALSE it is bearish. When there is a switch from bearish to bullish it is a buy signal and when it switches from bullish to bearish it is a sell signal. This HTML is updated just before the daily close each day, but push notifications for any trade signals are also sent by push bullet.

To receive these signals in real-time, subscribe to the following channels - it’s free for a limited time!

https://www.pushbullet.com/channel?tag=btc_signal

https://www.pushbullet.com/channel?tag=eth_signal

If you need some help to design your own trading signals/strategies, I am happy to help for a fee. email me at mark.ziemann{αt}gmail.com for any enquiries/suggestions/feedback.

This report is distributed for FREE under the MIT licence, but if you find it useful, consider a small tip.

XMR:4BGrdeAF5qyJQXjzWF4W5uCZF7WuwJU16BfPtgg1WJMnf33jZMtLvoF1jRtZBGpLtz5BQZaLYiBFJJC488anty64FB7SASD

library(png)
library(grid)
img <- readPNG("../images/donations.png")
grid.raster(img)

Reminder: this analysis is not financial advice.

suppressPackageStartupMessages({
  library("jsonlite")
  library("tidyverse")
  library("runner")
  library("quantmod")
  library("TTR")
  library("RPushbullet")
  library("kableExtra")
})

TESTING = FALSE
system("DATE=$(date -u) ; sed \"s/MYTIME/${DATE}/\" ../index0.html > ../index1.html")

mydate <- Sys.time()
attr(mydate, "tzone") <- "UTC"
mydate <- as.Date(mydate)

Get BTC price data

Obtaining BTC price data (daily) for the last 300 days.

URL="https://web-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical?symbol=BTC&convert=USD&interval=daily&count=300"
download.file(URL,destfile="btcdat.txt")
btcdat <- fromJSON("btcdat.txt")
price <- btcdat$data$quotes
price <- data.frame(  as.Date(price$time_close) , price$quote$USD$high, price$quote$USD$low, price$quote$USD$close)
colnames(price) <- c("date","high","low","close")
tail(price) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close
294 2022-06-28 21164.42 20228.81 20280.64
295 2022-06-29 20364.16 19937.79 20104.02
296 2022-06-30 20141.16 18729.66 19784.73
297 2022-07-01 20632.67 19073.71 19269.37
298 2022-07-02 19371.75 19027.08 19242.26
299 2022-07-03 19558.27 18966.95 19297.08

Now gather hourly price data for the last 23 hours.

URL="https://web-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical?symbol=BTC&convert=USD&interval=hourly&time_period=hourly&count=11"
download.file(URL,destfile="btcdat.txt")
btcdat <- fromJSON("btcdat.txt")
price2 <- btcdat$data$quotes
price2 <- data.frame( as.Date(price2$time_close) , price2$quote$USD$high, price2$quote$USD$low, price2$quote$USD$close,stringsAsFactors=FALSE)
colnames(price2) <- c("date","high","low","close")
tail(price2) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close
5 2022-07-04 19154.09 19108.33 19139.08
6 2022-07-04 19389.75 19136.71 19377.49
7 2022-07-04 19483.31 19367.68 19461.81
8 2022-07-04 19762.37 19460.99 19762.37
9 2022-07-04 19816.99 19673.57 19701.84
10 2022-07-04 19725.75 19550.29 19550.29
high <- max(price2[,2])
low <-  min(price2[,3])
close <- price2[nrow(price2),4]

df <- data.frame(date=mydate,high=high,low=low,close=close,stringsAsFactors=FALSE)
price <- rbind(price,df)
tail(price) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close
295 2022-06-29 20364.16 19937.79 20104.02
296 2022-06-30 20141.16 18729.66 19784.73
297 2022-07-01 20632.67 19073.71 19269.37
298 2022-07-02 19371.75 19027.08 19242.26
299 2022-07-03 19558.27 18966.95 19297.08
300 2022-07-04 19816.99 19084.24 19550.29
if ( TESTING == TRUE) {
  price[nrow(price),"close"] <- price[nrow(price),"close"] * 2
}
params <- read.table("https://mdz-analytics.com/altcoins/BTC/BTC_dat.txt", header=TRUE)
params %>% kbl(caption="BTC optimised backtested parameters") %>%  kable_paper("hover", full_width = F)
BTC optimised backtested parameters
indicator parameter meanROI totalROI ntrades ndays xhodl
SMA 43 1.163350 1875.6348 84 3263 6.758857
EMA 76 1.232865 968.4484 57 3263 3.489807
SMAcross 21,12 1.206000 2404.9715 74 3263 8.666323
EMAcross 48,18 1.794426 1836.8613 20 3263 6.619136
DMI 6 1.085680 3107.7862 171 3263 11.198919
TSI 69,59,5 1.278166 1798.8456 51 3263 6.482146
stoch 18,75,3 1.100545 2068.5788 111 3263 7.454131
RSI2 69,74 1.149731 1806.6849 96 3263 6.510396

BTC SMA indicator

Now to determine whether BTC has crossed the SMA line.

price2 <- price

n <- as.numeric(params[params$indicator == "SMA",2])

price2$ma <- SMA(Cl(price2),n=n)
price2$signal <- price2$close > price2$ma
tail(price2) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close ma signal
295 2022-06-29 20364.16 19937.79 20104.02 26230.63 FALSE
296 2022-06-30 20141.16 18729.66 19784.73 26022.82 FALSE
297 2022-07-01 20632.67 19073.71 19269.37 25765.96 FALSE
298 2022-07-02 19371.75 19027.08 19242.26 25534.37 FALSE
299 2022-07-03 19558.27 18966.95 19297.08 25298.67 FALSE
300 2022-07-04 19816.99 19084.24 19550.29 25048.12 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    btc_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    btc_signal="SELL"
  }
} else {
btc_signal <- "NONE"
}

if (today_signal==TRUE) {
 system("sed -i 's/BTC_SMA_DAILY/BULLISH/' ../index1.html")
 system("sed -i 's/BTC_SMA_COL/green/' ../index1.html")
} else {
 system("sed -i 's/BTC_SMA_DAILY/BEARISH/' ../index1.html")
 system("sed -i 's/BTC_SMA_COL/red/' ../index1.html")
}

message(paste("BTC SMA signal:",btc_signal))
## BTC SMA signal: NONE
plot(price2$close~as.Date(price2$date),type="l",
  xlab="Date",ylab="price (USD)",main="BTC SMA")
grid()
lines(price2$ma~ as.Date(price2$date) ,col="red")

Send a push notification.

MYNOTE = NULL

if ( btc_signal != "NONE") {
  MYNOTE <- paste("The BTC SMA signal is", btc_signal)
}

BTC SMA cross indicator

The SMA cross is a highly profitable strategy.

price2 <- price

n <- as.numeric(unlist(strsplit(params[params$indicator == "SMAcross",2],",")))
n1 <- n[1]
n2 <- n[2]

price2$ma1 <- SMA(Cl(price2),n=n1)
price2$ma2 <- SMA(Cl(price2),n=n2)

price2$signal <- price2$ma2 > price2$ma1
tail(price2) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close ma1 ma2 signal
295 2022-06-29 20364.16 19937.79 20104.02 22346.42 20569.62 FALSE
296 2022-06-30 20141.16 18729.66 19784.73 21854.64 20633.54 FALSE
297 2022-07-01 20632.67 19073.71 19269.37 21387.29 20526.55 FALSE
298 2022-07-02 19371.75 19027.08 19242.26 20953.07 20413.44 FALSE
299 2022-07-03 19558.27 18966.95 19297.08 20597.57 20295.65 FALSE
300 2022-07-04 19816.99 19084.24 19550.29 20457.71 20259.25 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    btc_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    btc_signal="SELL"
  }
} else {
btc_signal <- "NONE"
}

if (today_signal==TRUE) {
 system("sed -i 's/BTC_SMA_CROSS_DAILY/BULLISH/' ../index1.html")
 system("sed -i 's/BTC_SMA_CROSS_COL/green/' ../index1.html")
} else {
 system("sed -i 's/BTC_SMA_CROSS_DAILY/BEARISH/' ../index1.html")
 system("sed -i 's/BTC_SMA_CROSS_COL/red/' ../index1.html")
}

message(paste("BTC SMA cross signal is",btc_signal))
## BTC SMA cross signal is NONE
plot(price2$close~as.Date(price2$date),type="l",
  xlab="Date",ylab="price (USD)",main="BTC w 12/21 day SMA cross")
grid()
lines(price2$ma1~ as.Date(price2$date) ,col="red")
lines(price2$ma2~ as.Date(price2$date) ,col="blue")

Send a push notification.

if ( btc_signal != "NONE") {
  MYNOTE <- paste(MYNOTE, "", btc_signal)
}

BTC DMI indicator

Directional movement indicator is a good approach to identify trend changes.

n <- as.numeric(params[params$indicator == "DMI",2])

dmi.adx <- ADX(price[,c("high","low","close")],n=n)
price2 <- cbind(price,dmi.adx)
price2$signal <- dmi.adx[,1] > dmi.adx[,2]
tail(price2) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close DIp DIn DX ADX signal
295 2022-06-29 20364.16 19937.79 20104.02 11.202759 31.92161 48.04442 45.61667 FALSE
296 2022-06-30 20141.16 18729.66 19784.73 8.766389 43.59382 66.51507 49.09974 FALSE
297 2022-07-01 20632.67 19073.71 19269.37 13.859239 33.83985 41.88887 47.89793 FALSE
298 2022-07-02 19371.75 19027.08 19242.26 13.082641 32.70169 42.85101 47.05677 FALSE
299 2022-07-03 19558.27 18966.95 19297.08 14.992019 29.31937 32.33334 44.60287 FALSE
300 2022-07-04 19816.99 19084.24 19550.29 17.700132 25.41112 17.88626 40.15010 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    btc_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    btc_signal="SELL"
  }
} else {
  btc_signal <- "NONE"
}

if (today_signal==TRUE) {
 system("sed -i 's/BTC_DMI_DAILY/BULLISH/' ../index1.html")
 system("sed -i 's/BTC_DMI_COL/green/' ../index1.html")
} else {
 system("sed -i 's/BTC_DMI_DAILY/BEARISH/' ../index1.html")
 system("sed -i 's/BTC_DMI_COL/red/' ../index1.html")
}

message(paste("BTC DMI signal:",btc_signal))
## BTC DMI signal: NONE
price2 <- as.data.frame(price2)
par(mfrow=c(2,1))
plot(price2$close~as.Date(price2$date),type="l",
  xlab="Date",ylab="price (USD)",main="BTC USD price")
grid()
plot(price2$DIp~as.Date(price2$date),type="l", col="blue",
  xlab="Date",ylab="price (USD)",main="BTC 32d DMI")
grid()
lines(price2$DIn ~ as.Date(price2$date) ,col="red")

Send a push notification.

if ( btc_signal != "NONE") {
  MYNOTE <- paste(MYNOTE, "BTC DMI is flashing a", btc_signal)
}

BTC TSI indicator

Probably the best performing indicator across most price series data.

n <- as.numeric(unlist(strsplit(params[params$indicator == "TSI",2],",")))
n1 <- n[1]
n2 <- n[2]
ns <- n[3]

TSI <- function(x, n.first = 25, n.second = 13, n.signal = 7) {
  #True Strength Indicator
  #https://school.stockcharts.com/doku.php?id=technical_indicators:true_strength_index
  x <- try.xts(x, error = as.matrix)
  pc <- x - lag.xts(x, na.pad = T) #force lag.xts to get na padding
  dspc <- EMA(EMA(pc, n = n.first), n = n.second)
  dsapc <- EMA(EMA(abs(pc), n = n.first), n = n.second)

  tsi <- 100 * (dspc/dsapc)
  signal <- EMA(tsi, n = n.signal)
  r <- cbind(tsi, signal)
  r <- reclass(r, x)
  if (!is.null(dim(r))) colnames(r) <- c("tsi", "signal")
  return(r)
}

tsi <- TSI(price$close , n.first = n1, n.second = n2, n.signal = ns )
colnames(tsi) <- c("tsi","sig")

price2 <- cbind(price,tsi)
price2$signal <- tsi[,1] > tsi[,2]
tail(price2) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close tsi sig signal
295 2022-06-29 20364.16 19937.79 20104.02 -21.59234 -21.09054 FALSE
296 2022-06-30 20141.16 18729.66 19784.73 -21.85432 -21.34513 FALSE
297 2022-07-01 20632.67 19073.71 19269.37 -22.14294 -21.61107 FALSE
298 2022-07-02 19371.75 19027.08 19242.26 -22.41879 -21.88031 FALSE
299 2022-07-03 19558.27 18966.95 19297.08 -22.67393 -22.14485 FALSE
300 2022-07-04 19816.99 19084.24 19550.29 -22.88476 -22.39149 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    btc_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    btc_signal="SELL"
  }
} else {
  btc_signal <- "NONE"
}

if (today_signal==TRUE) {
 system("sed -i 's/BTC_TSI_DAILY/BULLISH/' ../index1.html")
 system("sed -i 's/BTC_TSI_COL/green/' ../index1.html")
} else {
 system("sed -i 's/BTC_TSI_DAILY/BEARISH/' ../index1.html")
 system("sed -i 's/BTC_TSI_COL/red/' ../index1.html")
}

message(paste("BTC TSI signal:",btc_signal))
## BTC TSI signal: NONE
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price")
grid()

plot(tsi[,1] ~ as.Date(price2$date),type="l",col="blue",
  xlab="Date",ylab="TSI",main="TSI")
lines(as.Date(price2$date), tsi[,2]  , col="red"  )
grid()

par(mfrow=c(1,1))

Send a push notification.

if ( btc_signal != "NONE") {
  MYNOTE <- paste(MYNOTE, "BTC TSI is flashing a", btc_signal)
}

BTC stochastic oscillator indicator

n <- as.numeric(unlist(strsplit(params[params$indicator == "stoch",2],",")))
n1 <- n[1]
n2 <- n[2]
n3 <- n[3]

sto <- stoch(HLC(price), nFastK=n1 , nFastD=n2 , nSlowD=n2 , bounded = TRUE, smooth=n3)

price2 <- cbind(price,sto)
price2$signal <- price2$fastK > price2$fastD

tail(price2) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close fastK fastD slowD signal
295 2022-06-29 20364.16 19937.79 20104.02 0.2282476 0.2538299 0.3847318 FALSE
296 2022-06-30 20141.16 18729.66 19784.73 0.2230773 0.2553514 0.3806730 FALSE
297 2022-07-01 20632.67 19073.71 19269.37 0.2394570 0.2571743 0.3767063 FALSE
298 2022-07-02 19371.75 19027.08 19242.26 0.2643719 0.2588220 0.3728196 TRUE
299 2022-07-03 19558.27 18966.95 19297.08 0.2995874 0.2600417 0.3689883 TRUE
300 2022-07-04 19816.99 19084.24 19550.29 0.3448080 0.2607117 0.3652066 TRUE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    btc_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    btc_signal="SELL"
  }
} else {
  btc_signal <- "NONE"
}

if (today_signal==TRUE) {
 system("sed -i 's/BTC_STOCH_DAILY/BULLISH/' ../index1.html")
 system("sed -i 's/BTC_STOCH_COL/green/' ../index1.html")
} else {
 system("sed -i 's/BTC_STOCH_DAILY/BEARISH/' ../index1.html")
 system("sed -i 's/BTC_STOCH_COL/red/' ../index1.html")
}

message(paste("BTC stoch signal:",btc_signal))
## BTC stoch signal: NONE
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price")
grid()

plot(price2$fastK ~ as.Date(price2$date),type="l",col="blue",
  xlab="Date",ylab="index",main="stochastic oscillator")
lines(as.Date(price2$date), price2$fastD  , col="red"  )
grid()

par(mfrow=c(1,1))

Send a push notification.

if ( btc_signal != "NONE") {
  MYNOTE <- paste(MYNOTE,"BTC Stoch is flashing a", btc_signal)
}

BTC double RSI indicator

n <- as.numeric(unlist(strsplit(params[params$indicator == "RSI2",2],",")))
n1 <- n[1]
n2 <- n[2]

rsi1 <- RSI(price$close,n=n1,maType=EMA)
rsi2 <- RSI(price$close,n=n2,maType=EMA)

price2 <- cbind(price,rsi1,rsi2)
price2$signal <- price2$rsi1 > price2$rsi2

tail(price2) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close rsi1 rsi2 signal
295 2022-06-29 20364.16 19937.79 20104.02 35.07874 35.47411 FALSE
296 2022-06-30 20141.16 18729.66 19784.73 34.69397 35.11488 FALSE
297 2022-07-01 20632.67 19073.71 19269.37 34.07300 34.53495 FALSE
298 2022-07-02 19371.75 19027.08 19242.26 34.04000 34.50415 FALSE
299 2022-07-03 19558.27 18966.95 19297.08 34.17268 34.62527 FALSE
300 2022-07-04 19816.99 19084.24 19550.29 34.79634 35.19400 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    btc_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    btc_signal="SELL"
  }
} else {
  btc_signal <- "NONE"
}

if (today_signal==TRUE) {
 system("sed -i 's/BTC_RSI_DAILY/BULLISH/' ../index1.html")
 system("sed -i 's/BTC_RSI_COL/green/' ../index1.html")
} else {
 system("sed -i 's/BTC_RSI_DAILY/BEARISH/' ../index1.html")
 system("sed -i 's/BTC_RSI_COL/red/' ../index1.html")
}

message(paste("BTC RSI signal:",btc_signal))
## BTC RSI signal: NONE
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price")
grid()

plot(price2$rsi1 ~ as.Date(price2$date),type="l",col="blue",
  xlab="Date",ylab="index",main="double RSI")
lines(as.Date(price2$date), price2$rsi2  , col="red"  )
grid()

par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price")
grid()

plot(price2$rsi1/price2$rsi2 ~ as.Date(price2$date),type="l",
  xlab="Date",ylab="RSI ratio",main="double RSI")
grid()
abline(h=1,lty=2,lwd=2)

par(mfrow=c(1,1))

Send a push notification.

if ( btc_signal != "NONE") {
  MYNOTE <- paste(MYNOTE,"BTC RSI2 is flashing a", btc_signal)
}

#if ( !is.null(MYNOTE) ) {
#  MYNOTE <- paste(MYNOTE,". Visit https://mdz-analytics.com/crypto/alerts.html for the details")
#  pbPost("note", "Crypto Alert", MYNOTE, channel="btc_signal")
#}

Get ETH price data

Obtaining ETH historical data (daily).

URL="https://web-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical?symbol=ETH&convert=USD&interval=daily&count=300"
download.file(URL,destfile="ethdat.txt")
ethdat <- fromJSON("ethdat.txt")
price <- ethdat$data$quotes
price <- data.frame( as.Date(price$time_close) , price$quote$USD$high, price$quote$USD$low, price$quote$USD$close)
colnames(price) <- c("date","high","low","close")
tail(price) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close
294 2022-06-28 1229.739 1141.160 1144.579
295 2022-06-29 1152.685 1092.099 1098.944
296 2022-06-30 1103.690 1009.095 1067.299
297 2022-07-01 1100.224 1040.151 1059.767
298 2022-07-02 1073.053 1033.962 1066.513
299 2022-07-03 1083.419 1044.006 1073.767

Now gather hourly price data for the last 23 hours.

URL="https://web-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical?symbol=ETH&convert=USD&interval=hourly&time_period=hourly&count=11"
download.file(URL,destfile="ethdat.txt")
ethdat <- fromJSON("ethdat.txt")
price2 <- ethdat$data$quotes
price2 <- data.frame( as.Date(price2$time_close)  , price2$quote$USD$high, price2$quote$USD$low, price2$quote$USD$close,stringsAsFactors=FALSE)
colnames(price2) <- c("date","high","low","close")
tail(price2) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close
5 2022-07-04 1053.196 1051.030 1051.787
6 2022-07-04 1066.719 1051.363 1066.540
7 2022-07-04 1074.830 1066.526 1073.826
8 2022-07-04 1094.295 1072.431 1094.295
9 2022-07-04 1106.450 1094.238 1106.387
10 2022-07-04 1106.814 1094.569 1094.569
high <- max(price2[,2])
low <- min(price2[,3])
close <- price2[nrow(price2),4]

df <- data.frame(date=Sys.Date(),high=high,low=low,close=close,stringsAsFactors=FALSE)
price <- rbind(price,df)
tail(price) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close
295 2022-06-29 1152.685 1092.099 1098.944
296 2022-06-30 1103.690 1009.095 1067.299
297 2022-07-01 1100.224 1040.151 1059.767
298 2022-07-02 1073.053 1033.962 1066.513
299 2022-07-03 1083.419 1044.006 1073.767
300 2022-07-04 1106.814 1048.396 1094.569
if ( TESTING == TRUE) {
  price[nrow(price),"Close"] <- price[nrow(price),"Close"] * 2
}
params <- read.table("https://mdz-analytics.com/altcoins/ETH/ETH_dat.txt", header=TRUE)
params %>% kbl(caption="ETH optimised backtested parameters") %>%  kable_paper("hover", full_width = F)
ETH optimised backtested parameters
indicator parameter meanROI totalROI ntrades ndays xhodl
SMA 34 1.747644 32115.470 67 2467 35.403176
EMA 17 1.163883 29146.841 130 2467 32.130644
SMAcross 27,5 1.618852 27858.643 46 2467 30.710572
EMAcross 16,13 2.634299 31742.967 30 2467 34.992539
DMI 16 1.891854 23110.349 60 2467 25.476188
TSI 101,7,20 1.368783 10773.280 49 2467 11.876156
stoch 20,5,36 1.237952 95850.138 75 2467 105.662452
RSI2 56,59 1.147941 2657.575 101 2467 2.929635

ETH SMA indicator

Now to determine whether ETH has crossed the SMA line.

price2 <- price

n <- as.numeric(params[params$indicator == "SMA",2])

price2$ma <- SMA(Cl(price2),n=n)
price2$signal <- price2$close > price2$ma
tail(price2) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close ma signal
295 2022-06-29 1152.685 1092.099 1098.944 1461.294 FALSE
296 2022-06-30 1103.690 1009.095 1067.299 1441.953 FALSE
297 2022-07-01 1100.224 1040.151 1059.767 1420.404 FALSE
298 2022-07-02 1073.053 1033.962 1066.513 1398.477 FALSE
299 2022-07-03 1083.419 1044.006 1073.767 1371.340 FALSE
300 2022-07-04 1106.814 1048.396 1094.569 1346.405 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    eth_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    eth_signal="SELL"
  }
} else {
  eth_signal <- "NONE"
}

if (today_signal==TRUE) {
 system("sed -i 's/ETH_SMA_DAILY/BULLISH/' ../index1.html")
 system("sed -i 's/ETH_SMA_COL/green/' ../index1.html")
} else {
 system("sed -i 's/ETH_SMA_DAILY/BEARISH/' ../index1.html")
 system("sed -i 's/ETH_SMA_COL/red/' ../index1.html")
}

message(paste("ETH SMA signal:",eth_signal))
## ETH SMA signal: NONE
plot(price2$close~as.Date(price2$date),type="l",
  xlab="Date",ylab="price (USD)",main="ETH w 34D MA")
grid()
lines(price2$ma~ as.Date(price2$date) ,col="red")

Send a push notification.

MYNOTE = NULL

if ( eth_signal != "NONE") {
  MYNOTE <- paste("The ETH SMA signal is", eth_signal)
}

ETH SMA cross indicator

The SMA cross is a highly profitable strategy.

price2 <- price

n <- as.numeric(unlist(strsplit(params[params$indicator == "SMAcross",2],",")))
n1 <- n[1]
n2 <- n[2]

price2$ma1 <- SMA(Cl(price2),n=n1)
price2$ma2 <- SMA(Cl(price2),n=n2)

price2$signal <- price2$ma2 > price2$ma1
tail(price2) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close ma1 ma2 signal
295 2022-06-29 1152.685 1092.099 1098.944 1361.413 1176.096 FALSE
296 2022-06-30 1103.690 1009.095 1067.299 1335.199 1140.867 FALSE
297 2022-07-01 1100.224 1040.151 1059.767 1307.723 1112.854 FALSE
298 2022-07-02 1073.053 1033.962 1066.513 1280.364 1087.420 FALSE
299 2022-07-03 1083.419 1044.006 1073.767 1251.271 1073.258 FALSE
300 2022-07-04 1106.814 1048.396 1094.569 1224.623 1072.383 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    eth_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    eth_signal="SELL"
  }
} else {
eth_signal <- "NONE"
}

if (today_signal==TRUE) {
 system("sed -i 's/ETH_SMA_CROSS_DAILY/BULLISH/' ../index1.html")
 system("sed -i 's/ETH_SMA_CROSS_COL/green/' ../index1.html")
} else {
 system("sed -i 's/ETH_SMA_CROSS_DAILY/BEARISH/' ../index1.html")
 system("sed -i 's/ETH_SMA_CROSS_COL/red/' ../index1.html")
}

message(paste("ETH SMA cross signal:",eth_signal))
## ETH SMA cross signal: NONE
plot(price2$close~as.Date(price2$date),type="l",
  xlab="Date",ylab="price (USD)",main="ETH w 5/27 day SMA cross")
grid()
lines(price2$ma1~ as.Date(price2$date) ,col="red")
lines(price2$ma2~ as.Date(price2$date) ,col="blue")

Send a push notification.

if ( eth_signal != "NONE") {
  MYNOTE <- paste(MYNOTE,"The ETH SMA cross signal is", eth_signal)
}

ETH DMI

n <- as.numeric(params[params$indicator == "DMI",2])

dmi.adx <- ADX(price[,c("high","low","close")],n=n)
price2 <- cbind(price,dmi.adx)
price2$signal <- dmi.adx[,1] > dmi.adx[,2]
tail(price2) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close DIp DIn DX ADX signal
295 2022-06-29 1152.685 1092.099 1098.944 13.76190 35.62348 44.26731 47.76770 FALSE
296 2022-06-30 1103.690 1009.095 1067.299 13.01210 38.46332 49.44344 47.87244 FALSE
297 2022-07-01 1100.224 1040.151 1059.767 12.54896 37.09430 49.44344 47.97063 FALSE
298 2022-07-02 1073.053 1033.962 1066.513 12.24642 36.58167 49.83864 48.08738 FALSE
299 2022-07-03 1083.419 1044.006 1073.767 12.60164 35.65711 47.77468 48.06783 FALSE
300 2022-07-04 1106.814 1048.396 1094.569 13.65619 34.28709 43.03188 47.75309 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    eth_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    eth_signal="SELL"
  }
} else {
  eth_signal <- "NONE"
}

if (today_signal==TRUE) {
 system("sed -i 's/ETH_DMI_DAILY/BULLISH/' ../index1.html")
 system("sed -i 's/ETH_DMI_COL/green/' ../index1.html")
} else {
 system("sed -i 's/ETH_DMI_DAILY/BEARISH/' ../index1.html")
 system("sed -i 's/ETH_DMI_COL/red/' ../index1.html")
}

message(paste("ETH DMI signal:",eth_signal))
## ETH DMI signal: NONE
par(mfrow=c(2,1))
plot(price2$close~as.Date(price2$date),type="l",
  xlab="Date",ylab="price (USD)",main="ETH USD price")
grid()
plot(price2$DIp~as.Date(price2$date),type="l", col="blue",
  xlab="Date",ylab="price (USD)",main="ETH 16d DMI")
grid()
lines(price2$DIn ~ as.Date(price2$date) ,col="red")

Send a push notification.

if ( eth_signal != "NONE") {
  MYNOTE <- paste(MYNOTE, "ETH DMI is flashing a", eth_signal)
}

ETH TSI indicator

Best indicator.

n <- as.numeric(unlist(strsplit(params[params$indicator == "TSI",2],",")))
n1 <- n[1]
n2 <- n[2]
ns <- n[3]

tsi <- TSI(price$close , n.first = n1, n.second = n2, n.signal = ns )
colnames(tsi) <- c("tsi","sig")

price2 <- cbind(price,tsi)
price2$signal <- tsi[,1] > tsi[,2]
tail(price2) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close tsi sig signal
295 2022-06-29 1152.685 1092.099 1098.944 -24.95332 -24.52690 FALSE
296 2022-06-30 1103.690 1009.095 1067.299 -25.25741 -24.59647 FALSE
297 2022-07-01 1100.224 1040.151 1059.767 -25.52169 -24.68459 FALSE
298 2022-07-02 1073.053 1033.962 1066.513 -25.66597 -24.77805 FALSE
299 2022-07-03 1083.419 1044.006 1073.767 -25.71507 -24.86729 FALSE
300 2022-07-04 1106.814 1048.396 1094.569 -25.57796 -24.93498 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    eth_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    eth_signal="SELL"
  }
} else {
  eth_signal <- "NONE"
}

if (today_signal==TRUE) {
 system("sed -i 's/ETH_TSI_DAILY/BULLISH/' ../index1.html")
 system("sed -i 's/ETH_TSI_COL/green/' ../index1.html")
} else {
 system("sed -i 's/ETH_TSI_DAILY/BEARISH/' ../index1.html")
 system("sed -i 's/ETH_TSI_COL/red/' ../index1.html")
}

message(paste("ETH TSI signal:",eth_signal))
## ETH TSI signal: NONE
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price")
grid()

plot(tsi[,1] ~ as.Date(price2$date),type="l",col="blue",
  xlab="Date",ylab="TSI",main="TSI")
lines(as.Date(price2$date), tsi[,2]  , col="red"  )
grid()

par(mfrow=c(1,1))

Send a push notification.

if ( eth_signal != "NONE") {
  MYNOTE <- paste(MYNOTE,"ETH TSI is flashing a ", eth_signal)
}

ETH stochastic oscillator indicator

n <- as.numeric(unlist(strsplit(params[params$indicator == "stoch",2],",")))
n1 <- n[1]
n2 <- n[2]
n3 <- n[3]

sto <- stoch(HLC(price), nFastK=n1 , nFastD=n2 , nSlowD=n2 , bounded = TRUE, smooth=n3)

price2 <- cbind(price,sto)
price2$signal <- price2$fastK > price2$fastD

tail(price2) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close fastK fastD slowD signal
295 2022-06-29 1152.685 1092.099 1098.944 0.1863697 0.1823511 0.1757180 TRUE
296 2022-06-30 1103.690 1009.095 1067.299 0.1869669 0.1844323 0.1787056 TRUE
297 2022-07-01 1100.224 1040.151 1059.767 0.1930858 0.1868895 0.1817101 TRUE
298 2022-07-02 1073.053 1033.962 1066.513 0.2020019 0.1907580 0.1847309 TRUE
299 2022-07-03 1083.419 1044.006 1073.767 0.2093972 0.1955643 0.1879990 TRUE
300 2022-07-04 1106.814 1048.396 1094.569 0.2164346 0.2015773 0.1918443 TRUE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    eth_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    eth_signal="SELL"
  }
} else {
  eth_signal <- "NONE"
}

if (today_signal==TRUE) {
 system("sed -i 's/ETH_STOCH_DAILY/BULLISH/' ../index1.html")
 system("sed -i 's/ETH_STOCH_COL/green/' ../index1.html")
} else {
 system("sed -i 's/ETH_STOCH_DAILY/BEARISH/' ../index1.html")
 system("sed -i 's/ETH_STOCH_COL/red/' ../index1.html")
}

message(paste("ETH stoch signal:",eth_signal))
## ETH stoch signal: NONE
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price")
grid()

plot(price2$fastK ~ as.Date(price2$date),type="l",col="blue",
  xlab="Date",ylab="index",main="stochastic oscillator")
lines(as.Date(price2$date), price2$fastD  , col="red"  )
grid()

par(mfrow=c(1,1))

Send a push notification.

if ( eth_signal != "NONE") {
  MYNOTE <- paste(MYNOTE,"ETH Stoch is flashing a ", eth_signal)
}

ETH double RSI indicator

n <- as.numeric(unlist(strsplit(params[params$indicator == "RSI2",2],",")))
n1 <- n[1]
n2 <- n[2]

rsi1 <- RSI(price$close,n=n1,maType=EMA)
rsi2 <- RSI(price$close,n=n2,maType=EMA)

price2 <- cbind(price,rsi1,rsi2)
price2$signal <- price2$rsi1 > price2$rsi2

tail(price2) %>% kbl() %>%  kable_paper("hover", full_width = F)
date high low close rsi1 rsi2 signal
295 2022-06-29 1152.685 1092.099 1098.944 34.17488 34.36202 FALSE
296 2022-06-30 1103.690 1009.095 1067.299 33.61753 33.83464 FALSE
297 2022-07-01 1100.224 1040.151 1059.767 33.48284 33.70727 FALSE
298 2022-07-02 1073.053 1033.962 1066.513 33.72929 33.93769 FALSE
299 2022-07-03 1083.419 1044.006 1073.767 34.00182 34.19215 FALSE
300 2022-07-04 1106.814 1048.396 1094.569 34.79868 34.93562 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    eth_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    eth_signal="SELL"
  }
} else {
  eth_signal <- "NONE"
}

if (today_signal==TRUE) {
 system("sed -i 's/ETH_RSI_DAILY/BULLISH/' ../index1.html")
 system("sed -i 's/ETH_RSI_COL/green/' ../index1.html")
} else {
 system("sed -i 's/ETH_RSI_DAILY/BEARISH/' ../index1.html")
 system("sed -i 's/ETH_RSI_COL/red/' ../index1.html")
}

message(paste("ETH RSI signal:",eth_signal))
## ETH RSI signal: NONE
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price")
grid()

plot(price2$rsi1 ~ as.Date(price2$date),type="l",col="blue",
  xlab="Date",ylab="index",main="double RSI")
lines(as.Date(price2$date), price2$rsi2  , col="red"  )
grid()

par(mfrow=c(1,1))

par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price")
grid()

plot(price2$rsi1/price2$rsi2 ~ as.Date(price2$date),type="l",
  xlab="Date",ylab="RSI ratio",main="double RSI")
grid()
abline(h=1,lty=2,lwd=2)

par(mfrow=c(1,1))

Send a push notification.

if ( eth_signal != "NONE") {
  MYNOTE <- paste(MYNOTE,"ETH RSI2 is flashing a", eth_signal)
}

#if ( !is.null(MYNOTE) ) {
#  MYNOTE <- paste(MYNOTE,". Visit https://mdz-analytics.com/crypto/alerts.html for the details")
#  pbPost("note", "Crypto Alert", MYNOTE, channel="eth_signal")
#}

Session information

For reproducibility

sessionInfo()
## R version 4.1.2 (2021-11-01)
## Platform: aarch64-unknown-linux-gnu (64-bit)
## Running under: Ubuntu 22.04 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/aarch64-linux-gnu/blas/libblas.so.3.10.0
## LAPACK: /usr/lib/aarch64-linux-gnu/lapack/liblapack.so.3.10.0
## 
## locale:
##  [1] LC_CTYPE=en_AU.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_AU.UTF-8        LC_COLLATE=en_AU.UTF-8    
##  [5] LC_MONETARY=en_AU.UTF-8    LC_MESSAGES=en_AU.UTF-8   
##  [7] LC_PAPER=en_AU.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_AU.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] grid      stats     graphics  grDevices utils     datasets  methods  
## [8] base     
## 
## other attached packages:
##  [1] kableExtra_1.3.4  RPushbullet_0.3.4 quantmod_0.4.20   TTR_0.24.3       
##  [5] xts_0.12.1        zoo_1.8-10        runner_0.4.1      forcats_0.5.1    
##  [9] stringr_1.4.0     dplyr_1.0.9       purrr_0.3.4       readr_2.1.2      
## [13] tidyr_1.2.0       tibble_3.1.7      ggplot2_3.3.6     tidyverse_1.3.1  
## [17] jsonlite_1.8.0    png_0.1-7        
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_1.0.8.3      svglite_2.1.0     lattice_0.20-45   lubridate_1.8.0  
##  [5] assertthat_0.2.1  digest_0.6.29     utf8_1.2.2        R6_2.5.1         
##  [9] cellranger_1.1.0  backports_1.4.1   reprex_2.0.1      evaluate_0.15    
## [13] httr_1.4.3        highr_0.9         pillar_1.7.0      rlang_1.0.2      
## [17] curl_4.3.2        readxl_1.4.0      rstudioapi_0.13   jquerylib_0.1.4  
## [21] rmarkdown_2.14    webshot_0.5.3     munsell_0.5.0     broom_0.8.0      
## [25] compiler_4.1.2    modelr_0.1.8      xfun_0.30         systemfonts_1.0.4
## [29] pkgconfig_2.0.3   htmltools_0.5.2   tidyselect_1.1.2  viridisLite_0.4.0
## [33] fansi_1.0.3       crayon_1.5.1      tzdb_0.3.0        dbplyr_2.1.1     
## [37] withr_2.5.0       gtable_0.3.0      lifecycle_1.0.1   DBI_1.1.2        
## [41] magrittr_2.0.3    scales_1.2.0      cli_3.3.0         stringi_1.7.6    
## [45] fs_1.5.2          xml2_1.3.3        bslib_0.3.1       ellipsis_0.3.2   
## [49] generics_0.1.2    vctrs_0.4.1       tools_4.1.2       glue_1.6.2       
## [53] hms_1.1.1         parallel_4.1.2    fastmap_1.1.0     yaml_2.3.5       
## [57] colorspace_2.0-3  rvest_1.0.2       knitr_1.39        haven_2.5.0      
## [61] sass_0.4.1